package queue.deque;

public class ArrayDeque<E> implements Deque<E> {
    int head = 0;
    int tail = 0;
    E[] array;

    public ArrayDeque(int capacity) {
        this.array = (E[]) new Object[capacity + 1];
    }

    int inCre(int num) {
        if (num + 1 >= array.length) {
            return 0;
        }
        return num + 1;
    }

    int deCre(int num) {
        if (num - 1 < 0) {
            return array.length - 1;
        }
        return num - 1;
    }

    @Override
    public boolean offerFirst(E e) {
        if (isFull()) {
            return false;
        }
        head = deCre(head);
        array[head] = e;
        return true;

    }

    @Override
    public boolean offerLast(E e) {
        if (isFull()) {
            return false;
        }
        array[tail] = e;
        tail = inCre(tail);
        return true;
    }

    @Override
    public E pollFirst() {
        if (isEmpty()) {
            return null;
        }
        E e = array[head];
        array[head] = null;
        head = inCre(head);
        return e;
    }

    @Override
    public E pollLast() {
        if (isEmpty()) {
            return null;
        }
        tail = deCre(tail);
        E e = array[tail];
        array[tail] = null;
        return e;
    }

    @Override
    public E peekFirst() {
        if(isEmpty()){
            return null;
        }
        return array[head];
    }

    @Override
    public E peekLast() {
        if(isEmpty()){
            return null;
        }
        return array[deCre(tail)];
    }

    @Override
    public boolean isEmpty() {
        return head == tail;
    }

    @Override
    public boolean isFull() {
        return (tail - head + array.length) % array.length == array.length - 1;
    }
}
